#pragma once

#include "Log.hpp"
#include "Epoller.hpp"
#include "Connection.hpp"
#include <memory>
#include <unordered_map>


namespace EpollModule
{
    using connection_t = std::shared_ptr<Connection>;
    const int ready_array_size = 64;
    /* 主要负责对所有的connection做管理*/
    class Reactor
    {
    private:
        std::shared_ptr<Epoller> _epoller; //所创建的epoll模型
        std::unordered_map<int,connection_t> _connections;   //fd:Connection 当前server所管理的所有连接
        bool _isrunning;
        struct epoll_event _ready_array[ready_array_size];
    public:
        Reactor()
            :_isrunning(false)
            ,_epoller(new Epoller())
        {
            _epoller->Init();   
        }

        ~Reactor()
        {
            
        }

        void InsertConnection(connection_t conn)
        {
            auto it = _connections.find(conn->GetSocketFd());
            if(it == _connections.end())
            {
                //1.将连接添加到server管理的unordered_map中
                _connections.insert(std::make_pair(conn->GetSocketFd(),conn));
                //2. 将连接写透内核中
                _epoller->Add(conn->GetSocketFd(),conn->GetEvent());
                //3.使connection 回指
                conn->SetOwner(this);
                LOG(LogGrade::DEBUG) << "添加成功";
            }
        }

        void DelConnection(int fd)
        {
            if(ExistConnection(fd))
            {
                _epoller->Del(fd);
                _connections[fd]->Close();
                _connections.erase(fd);
            }
        }

        bool ExistConnection(int fd)
        {
            return _connections.find(fd) != _connections.end();
        }

        //开启/关闭指定fd关心的事件
        void EnableReadOrWrite(int sockfd,bool read,bool write)
        {
            if(ExistConnection(sockfd))
            {
                uint32_t event = ((read ? EPOLLIN : 0) | (write ? EPOLLOUT : 0) | EPOLLET);
                _connections[sockfd]->SetEvent(event);
                _epoller->Update(sockfd,_connections[sockfd]->GetEvent());
            }
        }

        void Dispatcher(int n)
        {
            // 进行处理
            for (int i = 0; i < n; i++)
            {
                // 开始进行任务派发
                int sockfd = _ready_array[i].data.fd;     // 就绪的fd
                uint32_t revent = _ready_array[i].events; // 就绪的事件

                //将所有的异常、错误，统一转换成IO处的异常进行处理
                if ((revent & EPOLLERR) || (revent & EPOLLHUP))
                    revent = (EPOLLIN | EPOLLOUT);
                
                //调用connection中设置的回调函数，进行事件派发
                if ((revent & EPOLLIN) && ExistConnection(sockfd))
                    _connections[sockfd]->Recver();

                if ((revent & EPOLLOUT) && ExistConnection(sockfd))
                    _connections[sockfd]->Sender();
            }
        }

        void LoopOnce(int timeout)
        {
            int n = _epoller->Wait(_ready_array, ready_array_size,timeout);
            if(n > 0)
                Dispatcher(n);  //进程事件派发
        }

        void Loop()
        {
            _isrunning = true;
            int timeout = 1000;
            while (_isrunning)
            {
                PrintEpoll();   //打印所管理的连接
                LoopOnce(timeout);
            }
            _isrunning = false;
        }

        void Stop()
        {
            _isrunning = false;
        }

        void PrintEpoll()
        {
            for(auto &e: _connections)
            {
                cout << e.first << " ";
            }
            cout << endl;
        }
    };
}